package cn.duwey.scs.common.base;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BaseDao<T extends BaseEntity> extends SqlSessionDaoSupport {

    private Map<String, Class<T>> mapperEntityClassMap = new HashMap<>();

    @Autowired
    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        super.setSqlSessionFactory(sqlSessionFactory);
    }

    public int insert(Object parameter) {
        String statement = getStatement("save");
        return getSqlSession().insert(statement, parameter);
    }

    public int update(String statementId) {
        String statement = getStatement(statementId);
        return getSqlSession().update(statement);
    }

    public void update(String statementId, Object parameter) {
        String statement = getStatement(statementId);
        getSqlSession().update(statement, parameter);
    }

    public void delete(Serializable id) {
        delete("delete", id);
    }

    public void delete(String statementId, Serializable id) {
        String statement = getStatement(statementId);
        getSqlSession().delete(statement, id);
    }

    public void delete(String statementId, Object parameter) {
        String statement = getStatement(statementId);
        getSqlSession().delete(statement, parameter);
    }

    public T selectOne(Serializable id) {
        return selectOne("selectOne", id);
    }

    public T selectOne(String statementId, Object parameter) {
        String statement = getStatement(statementId);
        T t = getSqlSession().selectOne(statement, parameter);
        return t;
    }

    public List<T> selectList(String statementId) {
        String statement = getStatement(statementId);
        return getSqlSession().selectList(statement);
    }

    public List<T> selectList(String statementId, Object parameter) {
        String statement = getStatement(statementId);
        return getSqlSession().selectList(statement, parameter);
    }

    public List<T> selectAll() {
        String statement = getStatement("selectAll");
        return getSqlSession().selectList(statement);
    }

    private String getStatement(String statementId) {
//        Class<T> clazz = getEntityClass();
        Class clazz = this.getClass();
        return clazz.getName() + "." + statementId;
    }

    @SuppressWarnings("unchecked")
    private Class<T> getEntityClass() {
        Class clazz = this.getClass();

        if (mapperEntityClassMap.containsKey(clazz.getName())) {
            return mapperEntityClassMap.get(clazz.getName());
        }
        else {
            // 获取class的超类
            Type genericSuperclass = clazz.getGenericSuperclass();
            // 强转为参数类型
            ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
            // 获取真实参数
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            // BaseDao只有一个参数, 这个参数就是实体类
            Class<T> entityClass = (Class<T>) actualTypeArguments[0];

            mapperEntityClassMap.put(clazz.getName(), entityClass);

            return entityClass;
        }

    }
}
